package rpt

import (
	"context"
	"fmt"
	"gitee.com/alex_li/amazon-rpt/cmd/rpt/process/common"
	"gitee.com/alex_li/amazon-rpt/cmd/rpt/tpl"
	"gitee.com/alex_li/amazon-rpt/internal/db"
	"gitee.com/alex_li/amazon-rpt/internal/rpt"
	"github.com/gorhill/cronexpr"
	"github.com/lishimeng/app-starter"
	"github.com/lishimeng/go-log"
	"time"
)

// 创建报表

func Schedule(ctx context.Context) {
	//var err error
	//var clientIndex int
	//var client db.AmazonLwa
	for {
		select {
		case <-ctx.Done():
			return
		case <-time.After(10 * time.Second):
			getSchedule(ctx, func(schedule db.RtpSchedule) {
				handleSchedule(ctx, schedule)
			})

			//genDailyRpt(ctx, client)
		}
	}
}

func handleSchedule(ctx context.Context, schedule db.RtpSchedule) {
	var cronTab = schedule.Cron
	var curRun = schedule.NextRun // next run is the generation time of this rpt
	var templateKey = schedule.Template
	expr, err := cronexpr.Parse(cronTab)
	if err != nil {
		log.Info(err)
		return
	}

	template, err := tpl.GetTpl(templateKey)
	if err != nil {
		log.Info("template not found: %s", templateKey)
		log.Info(err)
		return
	}

	nextRun := expr.Next(curRun)

	duration := nextRun.Sub(curRun)
	startDate := curRun.Add(-duration)
	endDate := curRun.Add(-time.Hour * 24)
	startDateStr := startDate.Format("2006-01-02")
	endDateStr := endDate.Format("2006-01-02")
	log.Info("rpt duration: %s--%s", startDateStr, endDateStr)

	handleRptGroup(ctx, template, startDateStr, endDateStr, schedule, func(report db.AmazonRpt, err error) {
		schedule.NextRun = nextRun
		updateSchedule(schedule, report, err)
	})
}

func updateSchedule(schedule db.RtpSchedule, report db.AmazonRpt, err error) {
	if err != nil {
		schedule.LastState = db.ScheduleStateFail
		schedule.ScheduleMemo.Memo = fmt.Sprintf("%v", err)
	} else {
		schedule.LastState = db.ScheduleStateOk
		schedule.ScheduleMemo.Memo = "latest_rpt:" + report.Name
	}
	_, err = app.GetOrm().Context.Update(&schedule, "last_state", "memo", "next_run")
}

func handleRptGroup(ctx context.Context, template rpt.Template, startDate, endDate string, schedule db.RtpSchedule, afterCreate func(report db.AmazonRpt, err error)) {
	log.Info("-- ----------------------------------")
	log.Info("create rpt: %s", template.GetTplName())
	log.Info("duration: %s --> %s", startDate, endDate)
	log.Info("-- ----------------------------------")

	var i = 0
	for {
		select {
		case <-ctx.Done():
			return
		case <-time.After(time.Second):
			client, err := common.GetClient(i)
			if err != nil {
				log.Info(err)
				return
			}
			i++
			genRpt(ctx, template, startDate, endDate, schedule, client, afterCreate)
		}
	}
}

func genRpt(_ context.Context, template rpt.Template,
	startDate, endDate string, _ db.RtpSchedule,
	client db.AmazonLwa, onCreate func(report db.AmazonRpt, err error)) {

	rptName := rpt.GenRptName()
	report, err := createScheduleRpt(client.ClientId, rptName, startDate, endDate, template)
	if err != nil {
		log.Info("create rpt failed")
		log.Info(err)
		return
	}
	log.Info("rpt: %s", report.Name)
	if onCreate != nil {
		onCreate(report, err)
	}
	return
}

func getSchedule(_ context.Context, handle func(schedule db.RtpSchedule)) {
	var err error
	var schedules []db.RtpSchedule
	_, err = app.GetOrm().Context.
		QueryTable(new(db.RtpSchedule)).
		Filter("next_run__lt", time.Now()).
		OrderBy("next_run").
		Limit(1).
		All(&schedules)
	if err != nil {
		log.Info(err)
		return
	}
	if len(schedules) == 0 {
		//log.Info("no rpt schedules")
		return
	}
	var schedule = schedules[0]
	handle(schedule)
}
